//修改window.fetch使其支持timeout参数,和一些默认配置
//使用方法 fetch(url,fetchOpt)或fetch({...fetchOpt,url:url});
//fetchOpt中data参数会被转化为URLSearchParams，根据请求类型追加到url或取代原body参数
//
import QS from './query_string';

export default (function() {
  if (typeof window.fetch !== 'function') {
    console.error('@当前环境不支持fetch');
    return false;
  }
  const origin_fetch = window.fetch;

  const __default_opt = { //默认fetch配置
    method: 'POST',
    mode: 'cors',
    headers: {
      'X-Custom-Test': '1'
    },
    credentials: 'include',
    cache: 'no-store',
    timeout: 15000 //**超时时间(ms);
  };

  const __fetch = function(url = '', usr_opt = {}) {
    if (typeof url === 'object') { //判断如果第1个参数是Object则将其拆分为url和fetch配置两个参数
      if (url.constructor === Request) {
        throw new TypeError('[fetch]不支持传入Request');
      }
      url = Object.assign(usr_opt, url);
      let realUrl = typeof url.url === 'string' ? url.url : '';
      delete url.url;
      return __fetch(realUrl, url);
    }
    let body_str = '';
    let __last_obj = {
      headers: Object.assign({}, __default_opt.headers, usr_opt.headers || {})
    };

    let mid_opt = Object.assign({}, __default_opt, usr_opt);
    if (usr_opt.data) {
      if (mid_opt.method && !/(get|head)/i.test(mid_opt.method)) {
        usr_opt.body = usr_opt.data;
      } else {
        delete usr_opt.body;
        url += (/\?/.test(url) ? (/&$/.test(url) ? '' : '&' ): '?') + QS.stringify(usr_opt.data); //拼接url
      }
    }
    mid_opt = null;
    if (typeof usr_opt.body === 'object') {
      if (usr_opt.body.constructor === Array) {
        throw new TypeError('不能是数组');
      } else if (usr_opt.body.constructor === Object) {
        body_str = QS.stringify(usr_opt.body);
      }
    } else if (typeof usr_opt.body === 'string') {
      body_str = usr_opt.body;
    }
    if (body_str !== '') {
      __last_obj.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
      __last_obj.body = new URLSearchParams(body_str);
    }
    let final_opt = Object.assign({}, __default_opt, usr_opt, __last_obj); //最终传递到原fetch的配置
    //console.log('@@最终fetch、',url,final_opt);
    let fetch_promise = origin_fetch(url, final_opt); //原始fetch返回的promise;
    return new Promise(function(resolve, reject) {
      const timer = setTimeout(function() {
        reject(new Error('请求超时(' + final_opt.timeout + 'ms)'));
      }, final_opt.timeout);
      fetch_promise.then(function(res) {
        clearTimeout(timer);
        resolve(res);
      }, function(err) {
        clearTimeout(timer);
        reject(err);
      });
    });
  };

  Object.keys(origin_fetch).forEach(val => {
    __fetch[val] = origin_fetch[val];
  });
  __fetch.origin = origin_fetch;
  window.fetch = __fetch;
  return __fetch;
}());
